/*
 * Wazuh Vulnerability scanner
 * Copyright (C) 2015, Wazuh Inc.
 * March 8, 2024.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef _EVENT_SEND_REPORT_HPP
#define _EVENT_SEND_REPORT_HPP

#include "chainOfResponsability.hpp"
#include "loggerHelper.h"
#include "scanContext.hpp"
#include "socketClient.hpp"
#include "vulnerabilityScanner.hpp"

/**
 * @brief Class in charge to send formatted report messages.
 * This class is responsible for sending the vulnerability alert to the analysisd queue.
 *
 * @tparam TScanContext scan context type.
 */
template<typename TScanContext = ScanContext, typename TReportDispatcher = ReportDispatcher>
class TEventSendReport final : public AbstractHandler<std::shared_ptr<TScanContext>>
{
private:
    std::shared_ptr<TReportDispatcher> m_reportDispatcher;

public:
    // LCOV_EXCL_START
    /**
     * @brief Construct a new Send Report object
     *
     * @param reportDispatcher Report queue instance.
     */
    explicit TEventSendReport(std::shared_ptr<TReportDispatcher> reportDispatcher)
        : m_reportDispatcher(std::move(reportDispatcher))
    {
    }
    // LCOV_EXCL_STOP

    /**
     * @brief Handles request and passes control to the next step of the chain.
     *
     * @param data Scan context.
     * @return std::shared_ptr<TScanContext> Abstract handler.
     */
    std::shared_ptr<TScanContext> handleRequest(std::shared_ptr<TScanContext> data) override
    {
        for (const auto& [key, value] : data->m_alerts)
        {
            try
            {
                std::ostringstream oss;

                // 1:[001] (agent_name) ip->location:
                oss << LOCALFILE_MQ << ":"
                    << "[" << data->agentId() << "] (" << data->agentName() << ") " << data->agentIp() << "->"
                    << "vulnerability-detector"
                    << ":"
                    // Vulnerability report.
                    << value.dump().c_str();

                // The report is sent in another thread.
                m_reportDispatcher->push(oss.str());

                if (data->affectedComponentType() == AffectedComponentType::Package)
                {
                    logDebug2(WM_VULNSCAN_LOGTAG,
                              "Vulnerability %s report for agent ID %s, package: %s, cve: %s",
                              data->getType() == ScannerType::PackageInsert ? "detected" : "solved",
                              data->agentId().data(),
                              data->packageName().data(),
                              key.c_str());
                }
                else if (data->affectedComponentType() == AffectedComponentType::Os)
                {
                    logDebug2(WM_VULNSCAN_LOGTAG,
                              "Vulnerability report for agent ID %s, OS: %s, cve: %s",
                              data->agentId().data(),
                              data->osName().data(),
                              key.c_str());
                }
                else
                {
                    logWarn(WM_VULNSCAN_LOGTAG,
                            "Vulnerability report for agent ID %s, cve: %s",
                            data->agentId().data(),
                            key.c_str());
                }
            }
            catch (...)
            {
                logWarn(WM_VULNSCAN_LOGTAG, "Couldn't send vulnerability JSON report for %s:", key.c_str());
            }
        }
        return AbstractHandler<std::shared_ptr<TScanContext>>::handleRequest(std::move(data));
    }
};

using EventSendReport = TEventSendReport<>;

#endif // _EVENT_SEND_REPORT_HPP
